import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map.Entry;

public class ChartsArea extends GuiElement {
	
	charts_updateFiltersResults_Thread thread = new charts_updateFiltersResults_Thread();
	boolean thread_finished = false;
	boolean thread_gotUpdatedResults = false;
	
	BarChart lastfm_chart, topArtist_chart, saved_chart;
	Button saveResults,clearSaved, showLastFM;
	boolean dragging = false;
	float dragX;

	public ChartsArea (float x, float y, float w, float h) {
		this.x = x;
		this.y = y;
		width = w;
		height = h;
		
		topArtist_chart = new BarChart(x+45, y+300, w-80, 200, 2);
		
		saveResults = new Button("Save", (int)x+900, 0);
		clearSaved = new Button("Clear", (int)x+900, 0);
		showLastFM = new Button("Top", (int)x+904, 685);

		updateCharts();
		
	} 
	
	public void draw() {
		
		
		if (lastfm_chart != null && lastfm_chart.mouseOver()) {
			if (dragging) {
	            float d = (float)40*(GLOBAL.processing.mouseX - dragX) / width;
	            GLOBAL.lastfm_index_start -= (int)d;
	            if (GLOBAL.lastfm_index_start < 0)
	            	GLOBAL.lastfm_index_start = 0;
	            else if (GLOBAL.lastfm_index_start > GLOBAL.lastfm_TopArtistsNames.size()-10)
	            	GLOBAL.lastfm_index_start = GLOBAL.lastfm_TopArtistsNames.size()-10;
				dragX = GLOBAL.processing.mouseX;
			}
		}
		else if (topArtist_chart != null && topArtist_chart.mouseOver()) {
			if (dragging) {
	            float d = (float)40*(GLOBAL.processing.mouseX - dragX) / width;
	            GLOBAL.topArtists_index_start -= (int)d;
	            if (GLOBAL.topArtists_index_start < 0)
	            	GLOBAL.topArtists_index_start = 0;
	            else if (GLOBAL.topArtists_index_start + 10 > 50)
	            	GLOBAL.topArtists_index_start = 50 - 10;
	            else if (GLOBAL.topArtists_index_start > GLOBAL.charts_nPlaysPerArtist_sorted.size()-10)
	            	GLOBAL.topArtists_index_start = GLOBAL.charts_nPlaysPerArtist_sorted.size()-10;
				dragX = GLOBAL.processing.mouseX;
			}
		}
		else if (saved_chart != null && saved_chart.mouseOver()) {
			if (dragging) {
	            float d = (float)40*(GLOBAL.processing.mouseX - dragX) / width;
	            GLOBAL.savedChart_index_start -= (int)d;
	            if (GLOBAL.savedChart_index_start < 0)
	            	GLOBAL.savedChart_index_start = 0;
	            else if (GLOBAL.savedChart_index_start + 10 > 50)
	            	GLOBAL.savedChart_index_start = 50 - 10;
	            else if (GLOBAL.savedChart_index_start > GLOBAL.charts_nPlaysPerArtist_sortedSaved.length-10)
	            	GLOBAL.savedChart_index_start = GLOBAL.charts_nPlaysPerArtist_sortedSaved.length-10;
				dragX = GLOBAL.processing.mouseX;
			}
		}
		if (lastfm_chart != null)
			lastfm_chart.draw();
		if (saved_chart!= null)
			saved_chart.draw();
		topArtist_chart.draw();
		
		saveResults.y = (int) topArtist_chart.y - 40;
		saveResults.draw();
		
		if (GLOBAL.charts_nPlaysPerArtist_sortedSaved != null && GLOBAL.charts_nPlaysPerArtist_sortedSaved.length > 0) {
			clearSaved.y = (int) saved_chart.y - 40;
			clearSaved.draw();
		}
		showLastFM.draw();
		
		
		if (thread.isAlive()){
			//GLOBAL.loadingFun();
			GLOBAL.angleNationality = GLOBAL.loadingCircle((int)topArtist_chart.x+530,(int)topArtist_chart.y -25,GLOBAL.angleNationality); //60,697
		}
		
	}

	public void mousePressed() {
		if (!dragging) {
			dragging = true;
			dragX = GLOBAL.processing.mouseX;
		}
		if(saveResults.mouseOver())GLOBAL.saveChart();
		else if(clearSaved.mouseOver())GLOBAL.clearChart();
		else if (showLastFM.mouseOver()) {
			showLastFM.mouseClicked();
			updateCharts();
			if(showLastFM.state == false)
				lastfm_chart = null;
		}
	}

	public void mouseDragged() {
	}

	public void mouseReleased() {
		dragging = false;
	}
	
	
	// Update charts, display from 1 to 3 charts dynamically
	public void updateCharts() {
		float chart_height;
		float space_top = 60;
		float space_bottom = 60;
		float space_between = 60;
		if (GLOBAL.charts_nPlaysPerArtist_sortedSaved == null) {
			saved_chart = null;
			if (showLastFM.state == true) {
				// 2 charts
				chart_height = (height - space_bottom - space_top - space_between)/2;
				if (lastfm_chart == null) {				
					lastfm_chart = new BarChart(x + 45, y + 60, width - 80, 200, 1);
				}
				lastfm_chart.changePosition(x+45, y+space_top,width - 80 , chart_height);
				topArtist_chart.changePosition(x+45, y+space_top+chart_height+space_between, width - 80, chart_height);
			}
			else {
				// 1 chart
				lastfm_chart = null;
				chart_height = (height - space_bottom - space_top);
				//System.out.println(chart_height);
				topArtist_chart.changePosition(x+45, y+space_top, width-80, chart_height);
			}
		}
		else {
			if (showLastFM.state == true) {
				// 3 charts
				chart_height = (height - space_bottom - space_top - space_between*2)/3;
				if (saved_chart == null)
					saved_chart = new BarChart(x + 45, y + 60, width - 80, 200, 3);
				if (lastfm_chart == null) {				
					lastfm_chart = new BarChart(x + 45, y + 60, width - 80, 200, 1);
				}
				lastfm_chart.changePosition(x+45, y + space_top, width - 80, chart_height);
				saved_chart.changePosition(x+45, y + space_top + chart_height + space_between, width-80, chart_height);
				topArtist_chart.changePosition(x + 45, y + space_top+space_between*2 + chart_height*2, width-80, chart_height);
			}
			else {
				// 2 charts
				chart_height = (height - space_bottom - space_top - space_between)/2;
				if (saved_chart == null)
					saved_chart = new BarChart(x + 45, y + 60, width - 80, 200, 3);
				saved_chart.changePosition(x+45, y+space_top,width - 80 , chart_height);
				topArtist_chart.changePosition(x+45, y+space_top+chart_height+space_between, width - 80, chart_height);
			}
		}

	}
	
	public void addSavedChart() {
		saved_chart = new BarChart(x + 40, y + 60, width - 80, 200, 1);
	}	

	public void updateFiltersResults() {
		if(thread.isAlive())thread.stop();
		thread = new charts_updateFiltersResults_Thread();
		thread_finished=false;
		thread_gotUpdatedResults = false;
		thread.start();
	}

	
	public class charts_updateFiltersResults_Thread extends Thread{

		String ageString, completeSexString;
		int totUsers = 1;

		public void run() {

			Statement stmt;
			ResultSet res ;
			
			GLOBAL.charts_nPlaysPerArtist.clear();
			GLOBAL.charts_nPlaysPerArtist_sorted.clear();
			
			if(GLOBAL.nationalitiesSelected.size()==0)return;
						
			// Sex Strings
			String maleString=null, femaleString=null, unknownString;
			
			if(GLOBAL.selectionPanel.m.state)
				maleString = "sex = 'm' OR ";
			if(GLOBAL.selectionPanel.f.state)
				femaleString = "sex = 'f' OR ";
			unknownString = "sex = ''";
			
			// Complete Sex String
			completeSexString="";
			
			if(maleString!=null)
				completeSexString = maleString;
			if(femaleString!=null)
				completeSexString = completeSexString.concat(femaleString);
			completeSexString = completeSexString.concat(unknownString);
			
			
			// Age String
			
			ageString = "( age >= '"+ GLOBAL.ageStart +"' AND age<= '"+ GLOBAL.ageEnd+"' ) ";
			
			if (GLOBAL.age_undefinedSelected)
				ageString += " OR age = '' ";
			
			// Prepare nationalities selected
			String nat = GLOBAL.nationalitiesSelected.get(0).getName();
			if (GLOBAL.nationalitiesSelected.size() > 1)
				for (int i=1; i<GLOBAL.nationalitiesSelected.size(); i++) {
					nat = nat + "' OR nationality = '" + GLOBAL.nationalitiesSelected.get(i).name;
				}

			
			// user count
			try {				
				String sql = "SELECT count(*) as n from users as U " +
						"WHERE " +
						"( U.nationality = '"+nat+"') AND ( "+
						ageString+" ) AND ("+
						completeSexString+") ;";
//				System.out.println(sql);
				stmt = GLOBAL.user_db_con.createStatement();
				res = stmt.executeQuery(sql);
			}
			catch(SQLException e){
				System.out.println("Error creating or running statement: " + e.toString());
				return;
			}

			try{	
				totUsers = res.getInt("n");
				GLOBAL.totalUsersResult = totUsers;
			}
			catch(Exception e){
				System.out.println("Error processing results: " + e.toString());
				try{
					res.close();
					stmt.close();
				}
				catch(Exception ex) {}
				return;
			}


			try
			{

				//System.out.println(nat);
				String sql = "SELECT artist_name, plays " +
						"FROM ( users as U INNER JOIN plays as P on U.user_code = P.user_code ) as I " +
						"INNER JOIN artists as A on I.artist_code = A.artist_code " +
						"WHERE " +
						"( nationality == '"+nat+"') AND ( "+
						ageString+" ) AND ("+
						completeSexString+") ;";
				//System.out.println(sql);
				stmt = GLOBAL.user_db_con.createStatement();
				res = stmt.executeQuery(sql);

			}
			catch(SQLException e)
			{
				System.out.println("Error creating or running statement: " + e.toString());
				e.printStackTrace();
				return;
			}


			try
			{
				String name;
				float found_value;
				ValueMap current_value;
				
				int i =0;
				
				while(res.next())
				{
					name = res.getString("artist_name");
					found_value = res.getInt("plays");
					current_value = GLOBAL.charts_nPlaysPerArtist.get(name);
//					System.out.println(name+ " "+ current_value+" + "+found_value);
					if (current_value == null) {
//						System.out.println(name+ " "+found_value);
						GLOBAL.charts_nPlaysPerArtist.put(name, new ValueMap(name, found_value/totUsers));
					}
					else {
//						System.out.println(name+ " "+ current_value+" + "+found_value);
						GLOBAL.charts_nPlaysPerArtist.put(name, new ValueMap(name, current_value.value+(found_value/totUsers)));
//						System.out.println(name+ " "+ GLOBAL.charts_nPlaysPerArtist.get(name).value);
					}
					//System.out.println("-> "+ name);
					
					if (i%1000 == 0)
						GLOBAL.charts_nPlaysPerArtist_sorted = (HashMap<String, ValueMap>) GLOBAL.charts_nPlaysPerArtist.clone();
					
					i++;
				}
				
				GLOBAL.charts_nPlaysPerArtist_sorted = (HashMap<String, ValueMap>) GLOBAL.charts_nPlaysPerArtist.clone();
				thread_finished =true;

			}
			catch(Exception e){
				System.out.println("Error processing results from thread of top artists: " + e.toString());
				try{
					res.close();
					stmt.close();
				}
				catch(Exception ex) {}
				return;
			}

		}
	}
	
}
